#include "api.h"

void websocket_pkt_send(char *buf)
{
  struct mg_connection *c = NULL;

  // printf("wesocket_pkt_valid!!\n");
  for (c = mg_next(nc->mgr, NULL); c != NULL; c = mg_next(nc->mgr, c))
  {
    if (c == nc)
      continue; /* Don't send to the sender. */
    // printf("websocket pkt:%s\n",buf);
    mg_send_websocket_frame(c, WEBSOCKET_OP_TEXT, buf, strlen(buf));
  }
}


char *api_get_value(struct http_message *hm)
{
  const struct mg_str *body =
      hm->query_string.len > 0 ? &hm->query_string : &hm->body;

  cJSON *root = cJSON_CreateObject();

  cJSON_AddItemToObject(root, "key1", cJSON_CreateString("value1"));
  cJSON_AddItemToObject(root, "key2", cJSON_CreateString("value2"));

  // 如果需要返回数组
  cJSON *array = cJSON_CreateArray();
  cJSON *item1 = cJSON_CreateObject();
  cJSON_AddItemToObject(item1, "item_key1", cJSON_CreateString("item_value1"));
  cJSON_AddItemToObject(item1, "item_key2", cJSON_CreateString("item_value2"));
  cJSON_AddItemToArray(array, item1);
  cJSON_AddItemToObject(root, "items", array);

  char *rep = cJSON_Print(root);
  cJSON_Delete(root);

  return rep;
}

char *api_set_value(struct http_message *hm)
{
  const struct mg_str *body =
      hm->query_string.len > 0 ? &hm->query_string : &hm->body;

  // 解析JSON数据
  cJSON *json = cJSON_Parse(body->p);
  if (json == NULL)
  {
    return NULL; // 解析失败
  }
  // 假设我们要获取一个名为"key"的字段
  cJSON *key_item = cJSON_GetObjectItem(json, "key");
  if (key_item == NULL || !cJSON_IsString(key_item))
  {
    cJSON_Delete(json);
    return NULL; // 键不存在或不是字符串
  }
  const char *key_value = key_item->valuestring;
  // 在这里可以处理key_value，比如存储到数据库或进行其他操作
  printf("Received key: %s\n", key_value);


// ...existing code...
  // 修改 ./cfg/test.json文件的key值
  FILE *fp = fopen("./cfg/test.json", "r");
  if (fp != NULL) {
    fseek(fp, 0, SEEK_END);
    long len = ftell(fp);
    fseek(fp, 0, SEEK_SET);
    char *file_data = (char *)malloc(len + 1);
    fread(file_data, 1, len, fp);
    file_data[len] = '\0';
    fclose(fp);

    cJSON *file_json = cJSON_Parse(file_data);
    if (file_json != NULL) {
      // 假设key为"key"，你可以根据实际需要修改
      cJSON *file_key = cJSON_GetObjectItem(file_json, "key");
      if (file_key) {
        cJSON_ReplaceItemInObject(file_json, "key", cJSON_CreateString(key_value));
      } else {
        cJSON_AddItemToObject(file_json, "key", cJSON_CreateString(key_value));
      }
      // 写回文件
      char *new_json = cJSON_Print(file_json);
      fp = fopen("./cfg/test.json", "w");
      if (fp) {
        fwrite(new_json, 1, strlen(new_json), fp);
        fclose(fp);
      }
      free(new_json);
      cJSON_Delete(file_json);
    }
    free(file_data);
  }
// ...existing code...

  // 释放JSON对象
  cJSON_Delete(json);
  // 返回一个简单的响应

  cJSON *response = cJSON_CreateObject();
  cJSON_AddItemToObject(response, "status", cJSON_CreateString("success"));
  cJSON_AddItemToObject(response, "message", cJSON_CreateString("Value set successfully"));
  char *rep = cJSON_Print(response);
  cJSON_Delete(response);
  return rep; // 返回响应字符串

}

void api_import_cfg(struct mg_connection *nc, int ev, void *p)
{
  struct file_writer_data *data = (struct file_writer_data *)nc->user_data;
  struct mg_http_multipart_part *mp = (struct mg_http_multipart_part *)p;

  switch (ev)
  {
  case MG_EV_HTTP_PART_BEGIN:
  {
    if (data == NULL)
    {
      data = calloc(1, sizeof(struct file_writer_data));
      data->fp = fopen("./cfg/dtu.json", "w+");
      // data->fp = tmpfile();
      data->bytes_written = 0;

      if (data->fp == NULL)
      {
        mg_printf(nc, "%s",
                  "HTTP/1.1 500 Failed to open a file\r\n"
                  "Content-Length: 0\r\n\r\n");
        nc->flags |= MG_F_SEND_AND_CLOSE;
        free(data);
        return;
      }
      nc->user_data = (void *)data;
    }
    break;
  }
  case MG_EV_HTTP_PART_DATA:
  {
    if (fwrite(mp->data.p, 1, mp->data.len, data->fp) != mp->data.len)
    {
      mg_printf(nc, "%s",
                "HTTP/1.1 500 Failed to write to a file\r\n"
                "Content-Length: 0\r\n\r\n");
      nc->flags |= MG_F_SEND_AND_CLOSE;
      return;
    }
    data->bytes_written += mp->data.len;
    break;
  }
  case MG_EV_HTTP_PART_END:
  {
    // LOG_D("core","upload end");
    fseek(data->fp, 0, 0);
    char *payload = (char *)malloc(data->bytes_written + 1);
    memset(payload, 0, data->bytes_written + 1);
    fread(payload, data->bytes_written, 1, data->fp);

    mg_printf(nc,
              "HTTP/1.1 200 OK\r\n"
              "Content-Type: text/plain\r\n"
              "Connection: close\r\n\r\n"
              "%s\n\n",
              payload);
    nc->flags |= MG_F_SEND_AND_CLOSE;
    fclose(data->fp);
    free(data);
    free(payload);
    nc->user_data = NULL;
    break;
  }
  }
}

void api_update_plugin(struct mg_connection *nc, int ev, void *p)
{
  struct file_writer_data *data = (struct file_writer_data *)nc->user_data;
  struct mg_http_multipart_part *mp = (struct mg_http_multipart_part *)p;

  switch (ev)
  {
  case MG_EV_HTTP_PART_BEGIN:
  {
    if (data == NULL)
    {
      data = calloc(1, sizeof(struct file_writer_data));

      data->fp = fopen("./plugins/Modbus-RTU.so", "w");
      // data->fp = tmpfile();
      data->bytes_written = 0;

      if (data->fp == NULL)
      {
        mg_printf(nc, "%s",
                  "HTTP/1.1 500 Failed to open a file\r\n"
                  "Content-Length: 0\r\n\r\n");
        nc->flags |= MG_F_SEND_AND_CLOSE;
        free(data);
        return;
      }
      nc->user_data = (void *)data;
    }
    break;
  }
  case MG_EV_HTTP_PART_DATA:
  {
    if (fwrite(mp->data.p, 1, mp->data.len, data->fp) != mp->data.len)
    {
      mg_printf(nc, "%s",
                "HTTP/1.1 500 Failed to write to a file\r\n"
                "Content-Length: 0\r\n\r\n");
      nc->flags |= MG_F_SEND_AND_CLOSE;
      return;
    }
    data->bytes_written += mp->data.len;
    break;
  }
  case MG_EV_HTTP_PART_END:
  {
    fseek(data->fp, 0, 0);
    mg_printf(nc,
              "HTTP/1.1 200 OK\r\n"
              "Content-Type: text/plain\r\n"
              "Connection: close\r\n\r\n");
    nc->flags |= MG_F_SEND_AND_CLOSE;
    fclose(data->fp);
    free(data);
    nc->user_data = NULL;
    break;
  }
  }
}


int is_equal(const struct mg_str *s1, const struct mg_str *s2)
{
  return s1->len == s2->len && memcmp(s1->p, s2->p, s2->len) == 0;
}

int is_websocket(const struct mg_connection *nc)
{
  return nc->flags & MG_F_IS_WEBSOCKET;
}